<!DOCTYPE html>
<html  lang="zh-CN" >
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, maximum-scale=5, viewport-fit=cover">
    <title>Java收集器新谈 | 学为我用</title>
    <meta name="description" content="前言网上关于javaGC的帖子已经非常多了，这边主要是从历史到发展再到建议做一些整理。会涉及到一些底层，但不会特别深入。总之，就是口语化，可以用来聊天（吹牛），培训和面试。 内存Java内存总体上其实分为堆和栈，栈中有程序计数器，本地方法栈，方法栈，虚拟机栈；堆中又有新生代老年代，新生代中有包含eden区，Survivor区，Survivor分为S0和S1。一般的javaGC指的是针对堆空间的回收">
<meta property="og:type" content="article">
<meta property="og:title" content="Java收集器新谈">
<meta property="og:url" content="https://123zhangzhenbin.gitee.io/zzbomb/2020/10/13/202010131150-somequestion/index.html">
<meta property="og:site_name" content="学为我用">
<meta property="og:description" content="前言网上关于javaGC的帖子已经非常多了，这边主要是从历史到发展再到建议做一些整理。会涉及到一些底层，但不会特别深入。总之，就是口语化，可以用来聊天（吹牛），培训和面试。 内存Java内存总体上其实分为堆和栈，栈中有程序计数器，本地方法栈，方法栈，虚拟机栈；堆中又有新生代老年代，新生代中有包含eden区，Survivor区，Survivor分为S0和S1。一般的javaGC指的是针对堆空间的回收">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://123zhangzhenbin.gitee.io/zzbomb/2020/10/13/202010131150-somequestion/1.png">
<meta property="article:published_time" content="2020-10-13T03:52:08.000Z">
<meta property="article:modified_time" content="2021-07-06T04:06:08.566Z">
<meta property="article:author" content="章瑱彬">
<meta property="article:tag" content="java">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://123zhangzhenbin.gitee.io/zzbomb/2020/10/13/202010131150-somequestion/1.png">

    
    <link rel="icon" href="/zzbomb/images/favicon_128.ico" type="image/x-icon">

    
<link rel="stylesheet" href="/zzbomb/css/common.min.css">



    
    
    
    
        <link href="//cdn.jsdelivr.net/npm/lightgallery.js@1.1.3/dist/css/lightgallery.min.css" rel="stylesheet">
    
    
    
<link rel="stylesheet" href="/zzbomb/css/iconfont.min.css">

    
<meta name="generator" content="Hexo 4.2.1"></head>

    <body>
        <header class="header header-fixture">
    <div class="profile-search-wrap flex sm:block">
        
        
        <div class="profile sm:text-center md:px-1 lg:px-3 sm:pb-4 sm:pt-6">
            <a id="avatar" role="link" href="https://gitee.com/123zhangzhenbin" class="inline-block lg:w-16 lg:h-16 w-8 h-8 m-2" target="_blank" rel="noopener" rel="noreferrer" >
                <img src="/zzbomb/images/g.jpg" class="rounded-full" alt="avatar">
            </a>
            <h2 id="name" class="hidden lg:block">ZZB</h2>
            <h3 id="title" class="hidden xl:block">Java，大数据，人工智能，区块链</h3>
            
            <small id="location" class="hidden lg:block">
                <i class="iconfont icon-map-icon"></i>
                DongGuan, China
            </small>
            
        </div>
        
        
<div class="search flex-1 flex lg:inline-block sm:hidden lg:px-4 lg:mt-2 lg:mb-4 lg:w-full">
    <form id="search-form" class="my-auto flex-1 lg:border lg:border-solid lg:border-gray-200">
        <div class="input-group table bg-gray-100 lg:bg-white w-full">
            <input id="search-input" type="text" placeholder="搜索" class="inline-block w-full bg-gray-100 lg:bg-white">
            <span class="table-cell">
                <button name="search tigger button" disabled>
                    <i class="iconfont icon-search m-2"></i>
                </button>
            </span>
        </div>
    </form>
        
<script id="search-teamplate" type="text/html" data-path="/zzbomb/content.json">
    <div>
        <div class="search-header bg-gray-400">
            <input id="actual-search-input" model="keyword" ref="input" class="inline-block w-full h-10 px-2 py-1" placeholder="搜索" type="text">
        </div>
        <div class="search-result bg-gray-200">
            {{#each searchPosts}}
            <a href="/{{ path }}" class="result-item block px-2 pb-3 mb-1 pt-1 hover:bg-indigo-100">
                <i class="iconfont icon-file"></i>
                <h1 class="result-title inline font-medium text-lg">{{ title }}</h1>
                <p class="result-content text-gray-600 text-sm">{{{ text }}}</p>
            </a>
            {{/each}}
        </div>
    </div>
</script>

</div>


        <button name="menu toogle button" id="menu-toggle-btn" class="block sm:hidden p-3" role="button" aria-expanded="false">
            <i class="iconfont icon-hamburger"></i>
        </button>
    </div>
    <nav id="menu-nav" class="hidden sm:flex flex-col">
        
        
            <div class="menu-item menu-home" role="menuitem">
                <a href="/zzbomb/.">
                    <i class="iconfont icon-home" aria-hidden="true"></i>
                    <span class="menu-title">首页</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-archives" role="menuitem">
                <a href="/zzbomb/archives">
                    <i class="iconfont icon-archive" aria-hidden="true"></i>
                    <span class="menu-title">归档</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-categories" role="menuitem">
                <a href="/zzbomb/categories">
                    <i class="iconfont icon-folder" aria-hidden="true"></i>
                    <span class="menu-title">分类</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-tags" role="menuitem">
                <a href="/zzbomb/tags">
                    <i class="iconfont icon-tag" aria-hidden="true"></i>
                    <span class="menu-title">标签</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-repository" role="menuitem">
                <a href="/zzbomb/repository">
                    <i class="iconfont icon-project" aria-hidden="true"></i>
                    <span class="menu-title">项目</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-links" role="menuitem">
                <a href="/zzbomb/links">
                    <i class="iconfont icon-friend" aria-hidden="true"></i>
                    <span class="menu-title">友链</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-about" role="menuitem">
                <a href="/zzbomb/about">
                    <i class="iconfont icon-cup" aria-hidden="true"></i>
                    <span class="menu-title">关于</span>
                </a>
            </div>
        
        
<div class="social-links flex sm:flex-col lg:hidden mt-5">
    
        <span class="social-item text-center">
            <a href="https://gitee.com/123zhangzhenbin" target="_blank" rel="noopener">
                <i class="iconfont social-icon icon-github"></i>
                <span class="menu-title hidden lg:inline">menu.github</span>
            </a>
        </span>
    
</div>


    </nav>
</header>

        <section class="main-section">
            
    <main class="flex-1 px-4 py-12 md:px-5 lg:px-8 lg:py-4 relative min-h-screen">
    

    <article class="content article article-archives article-type-list" itemscope="">
        <header class="article-header">
            
    
        <h1 class="article-title text-lg" itemprop="name">
            Java收集器新谈
        </h1>
    



            <p class="article-meta mb-3 text-xs">
                <span class="article-date">
    <i class="iconfont icon-calendar-check"></i>
	<a href="/zzbomb/2020/10/13/202010131150-somequestion/" class="article-date">
	  <time datetime="2020-10-13T03:52:08.000Z" itemprop="datePublished">10月 13</time>
	</a>
</span>

                

                
    <span class="article-tags">
    <i class="iconfont icon-tag"></i>
    <a class="article-tag-link" href="/zzbomb/tags/java/" rel="tag">java</a>
  </span>


                <span class="_partial/post-comment"><i class="icon icon-comment"></i>
                    <a href="/zzbomb/2020/10/13/202010131150-somequestion/#comments" class="article-comment-link">
                        评论
                    </a>
                </span>
                

            </p>
        </header>
        <div class="marked-body article-body">
            <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>网上关于javaGC的帖子已经非常多了，这边主要是从历史到发展再到建议做一些整理。会涉及到一些底层，但不会特别深入。总之，就是口语化，可以用来聊天（吹牛），培训和面试。</p>
<h2 id="内存"><a href="#内存" class="headerlink" title="内存"></a>内存</h2><p>Java内存总体上其实分为堆和栈，栈中有程序计数器，本地方法栈，方法栈，虚拟机栈；堆中又有新生代老年代，新生代中有包含eden区，Survivor区，Survivor分为S0和S1。一般的javaGC指的是针对堆空间的回收算法。</p>
<h2 id="GC的大体部奏"><a href="#GC的大体部奏" class="headerlink" title="GC的大体部奏"></a>GC的大体部奏</h2><p>总的来说GC分为两部，第一步是找到内存中不再使用的对象，第二步就是回收这些对象的内存。<br>在第一步找到内存中不再使用的对象这件事上，有两种方式。第一种叫做引用计数器法，第二种叫根目录搜索法。<br>在清除数据这件事上，java的GC就分为了三大派系：</p>
<ol>
<li><p>标记-复制<br>过程：将内存划分成相等大小的两个区间，每次回收前，会将存活的对象完全复制一份到另一个区间，然后全量清除当前区间。<br>本方法效率相对标记算法会有所提升，但是空间使用率降低到了50%。在JVM中，最明显的使用是S1空间和S2空间。</p>
</li>
<li><p>标记-清理<br>过程：先通过上述两种方式识别出需要回收的对象，并进行标记，然后将标记的数据清除掉。<br>本方法是一切垃圾回收算法的基础，其他的算法也都是基于这个算法优化而来的。但是本算法也有很多缺陷：1 容易产生内存碎片， 2 效率不高，标记和清除两个步骤都比较慢</p>
</li>
<li><p>标记-整理<br>过程：和标记-清除算法有点相似，只不过，这里的清除阶段动作为将失效的对象移到空间末尾，然后一次性将末尾的空间清除。<br>本算法效率一般，但是可以防止内存碎片的产生，因此广泛引用于GC收集器中。</p>
</li>
</ol>
<h2 id="谈谈收集器的历史"><a href="#谈谈收集器的历史" class="headerlink" title="谈谈收集器的历史"></a>谈谈收集器的历史</h2><p>Java收集器的历史可以大体划分为5个阶段。</p>
<h3 id="第一阶段：Serial（串行）收集器"><a href="#第一阶段：Serial（串行）收集器" class="headerlink" title="第一阶段：Serial（串行）收集器"></a>第一阶段：Serial（串行）收集器</h3><p>在1.3之前，java只支持serial收集器。<br>这一阶段的收集器包含了新生代的serial收集器和老年代的serialOld收集器。</p>
<h4 id="serial"><a href="#serial" class="headerlink" title="serial"></a>serial</h4><p>单线程，新生代收集器。采用复制算法。</p>
<h4 id="serialOld"><a href="#serialOld" class="headerlink" title="serialOld"></a>serialOld</h4><p>单线程，老年代，标记整理算法。Stop-the-world</p>
<p>开启方式 -XX:+UseSerialGC</p>
<h3 id="第二阶段：Parallel（并行）收集器"><a href="#第二阶段：Parallel（并行）收集器" class="headerlink" title="第二阶段：Parallel（并行）收集器"></a>第二阶段：Parallel（并行）收集器</h3><p>Parallel收集器也称吞吐量收集器，相比Serial收集器，Parallel最主要的优势在于使用多线程去完成垃圾清理工作，这样可以充分利用多核的特性，大幅降低gc时间。</p>
<h4 id="ParallelGC-PS-Scavenge"><a href="#ParallelGC-PS-Scavenge" class="headerlink" title="ParallelGC (PS Scavenge)"></a>ParallelGC (PS Scavenge)</h4><p>多线程，新生代收集器，采用复制算法，注重吞吐量，可用性可控。</p>
<h4 id="ParallelOldGC-PS-MarkSweep"><a href="#ParallelOldGC-PS-MarkSweep" class="headerlink" title="ParallelOldGC (PS MarkSweep)"></a>ParallelOldGC (PS MarkSweep)</h4><p>多线程，老年代，标记整理算法。Stop-the-world，配合ParallelGC使用，应用于高吞吐量场景。PS MarkSweep默认的实现实际上是<br>这一阶段的收集器的代码包是独立于serial/serialOld的，所以为了方便区分，在收集器名称上加了PS前缀。在1.7和1.8作为默认的收集器。</p>
<p>开启方式<br>-XX:+UseParallelGC -XX:+UseParallelOldGC</p>
<h3 id="第三阶段：CMS（并发）收集器"><a href="#第三阶段：CMS（并发）收集器" class="headerlink" title="第三阶段：CMS（并发）收集器"></a>第三阶段：CMS（并发）收集器</h3><p>1.6开始提供了CMS收集器，这一阶段的收集器产生了负责新生代的ParNew收集器和负责老年CMS收集器，值得注意的是，这一阶段是还是使用的是第一代GC框架代码包，即Serial/Serial Old/ParNew/CMS都在这个代码包内；在该代码包内的young collector和old collector可以任意搭配使用，所谓的“mix-and-match”。</p>
<h4 id="ParNew"><a href="#ParNew" class="headerlink" title="ParNew"></a>ParNew</h4><p>多线程，新生代收集器，采用复制算法。serial收集器的多线程版本。</p>
<h4 id="CMS收集器"><a href="#CMS收集器" class="headerlink" title="CMS收集器"></a>CMS收集器</h4><p>多线程，老年代，标记清除算法。非Stop-the-word,配合ParNew使用，应用于高可用场景。<br>分为四个步骤:初始标记,并发标记,重新标记,并发清除<br>其中，初始标记和重新标记会阻塞用户线程，其他不会。</p>
<p>优点是高可用。<br>缺点也很明显：1 费性能。2 由于非阻塞，并发标记阶段，无法处理用户当前在产生的垃圾。3 容易产生内存碎片，从而频繁触发fullGC。</p>
<p>开启方式<br>-XX:+UseParNewGC -XX:+UseConcMarkSweepGC</p>
<h3 id="第四阶段：G1收集器"><a href="#第四阶段：G1收集器" class="headerlink" title="第四阶段：G1收集器"></a>第四阶段：G1收集器</h3><p>模糊新生代和老年代的概念，但仍然是分代收集的思想，只不过将内存划分为多个Region区间，将内存化整为零。每次只回收一部分的Region。<br>低延迟，多线程，标记整理算法，非阻塞。<br>G1收集器从1.9开始作为默认的收集器。</p>
<p>开启方式<br>-XX:+UseG1GC</p>
<h3 id="第五阶段：ZGC"><a href="#第五阶段：ZGC" class="headerlink" title="第五阶段：ZGC"></a>第五阶段：ZGC</h3><p>低延迟，压缩，非阻塞。吞吐量也能达到Parallel Scavenge的99%，更是超过了G1。<br>有几个亮点需要提一下1 使用了虚拟内存页技术，在linux里就是mmap（所以好像目前支持linux?） 2 完全取消了分代概念<br>java11引入，值得注意的是..java14版本以后悄咪咪的把CMS给删掉了！<br>关于ZGC有几篇文章写得非常详细：</p>
<p><a href="https://developer.aliyun.com/article/726120" target="_blank" rel="noopener">带你读《新一代垃圾回收器ZGC设计与实现》之二：ZGC内存管理</a></p>
<p><a href="https://developer.aliyun.com/article/726110" target="_blank" rel="noopener">带你读《新一代垃圾回收器ZGC设计与实现》之三：ZGC线程</a></p>
<p>开启方式<br>-XX:+UseZGC</p>
<h2 id="说说GC新生代老年代搭配的事"><a href="#说说GC新生代老年代搭配的事" class="headerlink" title="说说GC新生代老年代搭配的事"></a>说说GC新生代老年代搭配的事</h2><p>如下图所示，书本中黑线部分表示的是可搭配的组合。红线部分表示一般的组合选择方式。<br><img src="/zzbomb/2020/10/13/202010131150-somequestion/1.png" alt="1"></p>
<p>Serial + SerialOld : 适合老版本java单机使用的小程序。<br>ParNew + CMS : 适合1.7版本以前低延迟要求的程序。<br>Parallel + Parallel Old（PS Scavenge + Ps MarkSweep）: 适合高吞吐率的应用场景，在java11前比较推荐。目前是大数据应用推荐的收集器组合。<br>G1 ：低延迟非阻塞并发场景，1.8版本以后的web程序推荐使用本收集器，往往比CMS好，毕竟CMS在14版本中悄咪咪的被删掉了。<br>ZGC : 官方说的好像很牛逼。可以试试。</p>

        </div>
        
<blockquote class="copyright">
    <p><strong>本文链接 : </strong><a class="permalink" href="https://123zhangzhenbin.gitee.io/zzbomb/2020/10/13/202010131150-somequestion/">https://123zhangzhenbin.gitee.io/zzbomb/2020/10/13/202010131150-somequestion/</a></p>
    <p><strong>This article is available under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank" rel="noopener noreferrer">Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)</a> License</strong></p>
</blockquote>


    </article>
    
    <section id="comments">
        
    </section>


    

</main>


<aside style="" id="sidebar" class="aside aside-fixture">
    <div class="toc-sidebar">
        <nav id="toc" class="article-toc">
            <h3 class="toc-title">文章目录</h3>
            <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#前言"><span class="toc-number">1.</span> <span class="toc-text">前言</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#内存"><span class="toc-number">2.</span> <span class="toc-text">内存</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#GC的大体部奏"><span class="toc-number">3.</span> <span class="toc-text">GC的大体部奏</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#谈谈收集器的历史"><span class="toc-number">4.</span> <span class="toc-text">谈谈收集器的历史</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#第一阶段：Serial（串行）收集器"><span class="toc-number">4.1.</span> <span class="toc-text">第一阶段：Serial（串行）收集器</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#serial"><span class="toc-number">4.1.1.</span> <span class="toc-text">serial</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#serialOld"><span class="toc-number">4.1.2.</span> <span class="toc-text">serialOld</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#第二阶段：Parallel（并行）收集器"><span class="toc-number">4.2.</span> <span class="toc-text">第二阶段：Parallel（并行）收集器</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#ParallelGC-PS-Scavenge"><span class="toc-number">4.2.1.</span> <span class="toc-text">ParallelGC (PS Scavenge)</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ParallelOldGC-PS-MarkSweep"><span class="toc-number">4.2.2.</span> <span class="toc-text">ParallelOldGC (PS MarkSweep)</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#第三阶段：CMS（并发）收集器"><span class="toc-number">4.3.</span> <span class="toc-text">第三阶段：CMS（并发）收集器</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#ParNew"><span class="toc-number">4.3.1.</span> <span class="toc-text">ParNew</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#CMS收集器"><span class="toc-number">4.3.2.</span> <span class="toc-text">CMS收集器</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#第四阶段：G1收集器"><span class="toc-number">4.4.</span> <span class="toc-text">第四阶段：G1收集器</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#第五阶段：ZGC"><span class="toc-number">4.5.</span> <span class="toc-text">第五阶段：ZGC</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#说说GC新生代老年代搭配的事"><span class="toc-number">5.</span> <span class="toc-text">说说GC新生代老年代搭配的事</span></a></li></ol>
        </nav>
    </div>
</aside>





        </section>
        <footer class="hidden lg:block fixed bottom-0 left-0 sm:w-1/12 lg:w-1/6 bg-gray-100 z-40">
    
    <div class="footer-social-links">
        
            <a href="https://gitee.com/123zhangzhenbin" target="_blank" rel="noopener">
                <i class="iconfont icon-github"></i>
            </a>
        
    </div>
    
    <p style="display: block;text-align: center;font-size: 13px;"><a href="https://beian.miit.gov.cn/" target="_blank">粤ICP备16013026号</a></p>
    
        <p class="footer-custom"><a href="https://beian.miit.gov.cn/" target="_blank">粤ICP备16013026号</a></p>
        <p class="theme-brand">Theme by <a href="https://github.com/fengkx/hexo-theme-purer" target="_blank" rel="nofollow noopener noreferrer noopener">hexo-theme-purer</a></p>

    
</footer>

        <div id="mask" class="hidden mask fixed inset-0 bg-gray-900 opacity-75 z-40"></div>
        <div id="search-view-container" class="hidden shadow-xl"></div>
        
<script src="/zzbomb/js/dom-event.min.js"></script>

<script src="//cdn.jsdelivr.net/npm/yox@1.0.0-alpha.121/dist/standard/prod/yox.min.js"></script>


<script src="/zzbomb/js/search.min.js"></script>



    <script src="//cdn.jsdelivr.net/npm/lightgallery.js@1.1.3/dist/js/lightgallery.min.js"></script>
    
<script src="/zzbomb/js/light-gallery.min.js"></script>





    </body>
</html>
